package com.yougong.common.exception;

import cn.dev33.satoken.exception.DisableLoginException;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import com.yougong.common.api.CommonResult;
import com.yougong.common.api.ResultCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 全局异常处理
 * Created on 2020/2/27.
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    private static final Pattern pattern = Pattern.compile("([\\s\\S]*)([a-zA-Z]){5}([\\s\\S]*)");

    @ResponseBody
    @ExceptionHandler(value = ApiException.class)
    public CommonResult handle(ApiException e) {
        log.error(e.getMessage());
        if (e.getErrorCode().equals(ResultCode.FAILED)) {
            return CommonResult.failed(e.getErrorCode());
        }
        return CommonResult.failed(e.getMessage());
    }

    @ResponseBody
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public CommonResult handleValidException(MethodArgumentNotValidException e) {
        log.error(e.getMessage());
        BindingResult bindingResult = e.getBindingResult();
        String message = null;
        if (bindingResult.hasErrors()) {
            FieldError fieldError = bindingResult.getFieldError();
            if (fieldError != null) {
                message = fieldError.getField() + fieldError.getDefaultMessage();
            }
        }
        return CommonResult.validateFailed(message);
    }

    @ResponseBody
    @ExceptionHandler(value = BindException.class)
    public CommonResult handleValidException(BindException e) {
        log.error(e.getMessage());
        BindingResult bindingResult = e.getBindingResult();
        String message = null;
        if (bindingResult.hasErrors()) {
            FieldError fieldError = bindingResult.getFieldError();
            if (fieldError != null) {
                message = fieldError.getField() + fieldError.getDefaultMessage();
            }
        }
        return CommonResult.validateFailed(message);
    }

    @ResponseBody
    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    public CommonResult httpMessageNotReadableException(HttpMessageNotReadableException e) {
        log.error(e.getMessage());

        String message = "";

        if (e.getMessage().contains("JSON parse error: Cannot deserialize value of type `java.time.LocalDateTime")) {
            message = "时间格式有误,应该为 yyyy-MM-dd HH:mm:ss";
        }

        return CommonResult.failed(message);
    }

    /**
     * 处理不存在请求方式
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    public CommonResult httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        log.error(e.getMessage());

        String message = e.getMessage() + "该请求方式不正确";

        return CommonResult.failed(message);
    }

    /**
     * saToken 全局异常拦截
     *
     * @date: 2022/4/11
     * @author: MuChen
     */
    @ResponseBody
    @ExceptionHandler(value = {Exception.class, RuntimeException.class})
    public CommonResult jsonExceptionHandler(HttpServletRequest request, Exception exception) {
        String msg = "";
        // 如果是未登录异常
        if (exception instanceof NotLoginException) {
            NotLoginException ee = (NotLoginException) exception;
            msg = "未登录";
            return CommonResult.unauthorized(null);
        }
        // 如果是角色异常
        else if (exception instanceof NotRoleException) {
            msg = "角色不存在";
        }
        // 如果是权限异常
        else if (exception instanceof NotPermissionException) {
            msg = "权限不足";
            return CommonResult.forbidden(null);
            // 如果是被封禁异常
        } else if (exception instanceof DisableLoginException) {
            DisableLoginException ee = (DisableLoginException) exception;
            msg = "账号被封禁：" + ee.getDisableTime() + "秒后解封";
        } else {
            log.error(exception.getMessage(), exception);
            Matcher matcher = pattern.matcher(exception.getMessage());
            if (exception.getMessage() == null || matcher.matches()) {
                log.error(exception.getMessage());
                //如果错误为空或者有太多英文，不予显示
                return CommonResult.failed();
            }
            msg = exception.getMessage();
        }
        return CommonResult.failed(msg);
    }
}
